package com.winxuan.channel.service.member.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Service;

import com.winxuan.channel.model.member.Resource;
import com.winxuan.channel.model.member.Role;
import com.winxuan.channel.service.member.ResourceService;
import com.winxuan.support.dao.BaseDao;
import com.winxuan.support.dao.Finder;
import com.winxuan.support.dao.ParametersFinder;

/**
 * @ ResourceServiceImpl.java 
 * To:��Դ����
 * Warn:

 * Note:winxuan.com
 * VERSION       DATE            BY       CHANGE/COMMENT
 * 1.0          2011-5-8          HideHai         2011-5-8
 */
@Service("resourceService")
public class ResourceServiceImpl implements ResourceService,FilterInvocationSecurityMetadataSource {
	private Logger log = LoggerFactory.getLogger(Thread.class);
	private BaseDao baseDao;
	private static Map<String,Collection<ConfigAttribute>> resourceMap = null;

	/**
	 * ����������Դ
	 */
	//@PostConstruct
	public void init(){
		log.info("==================-Loading resource begin -=================");
		resourceMap  = new HashMap<String, Collection<ConfigAttribute>>();
		List<Resource> resources = loadEnableResources();
		for(Resource r : resources){
			resourceMap.put(r.getUrl(),listToConllection(r.getRoles()));
		}
		log.info("=======================-Loading resource over -==============");
	}

	public Collection<ConfigAttribute> listToConllection(List<Role> roles){
		List<ConfigAttribute> list = new ArrayList<ConfigAttribute>();
		for(Role r:roles){
			list.add(new SecurityConfig(r.getName()));
		}
		return list;
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();
		for(Map.Entry<String,Collection<ConfigAttribute>> entry : resourceMap.entrySet()){
			allAttributes.addAll(entry.getValue());
		}
		return allAttributes;
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Object obj)
	throws IllegalArgumentException {
		String requestUrl = ((FilterInvocation) obj).getRequestUrl();
        if(resourceMap == null) {  
            init();  
        }  
        return resourceMap.get(requestUrl); 
	}

	@Override
	public boolean supports(Class<?> arg0) {
		return true;
	}

	@Override
	public List<Resource> loadAllResources() {
		Finder finder = new ParametersFinder() {
			@Override
			public String genQueryString() {
				StringBuffer sb=new StringBuffer("SELECT r FROM Resource r WHERE 1=1");
				return sb.toString();
			}
		};
		return baseDao.find(finder);
	}

	public void setBaseDao(BaseDao baseDao) {
		this.baseDao = baseDao;
	}

	@Override
	public boolean addResource(Resource resource) {
		Integer newid =  (Integer) baseDao.save(resource);
		return newid !=0;
	}

	@Override
	public List<Resource> loadEnableResources() {
		Finder finder = new ParametersFinder() {
			@Override
			public String genQueryString() {
				StringBuffer sb=new StringBuffer("SELECT r FROM Resource r WHERE 1=1 AND r.enable=true");
				return sb.toString();
			}
		};
		return baseDao.find(finder);
	}

	@Override
	public Resource getResource(Integer id) {
		Resource resource = (Resource) baseDao.get(Resource.class, id);
		return resource;
	}

	@Override
	public boolean deleteResource(Resource resource) {
		baseDao.delete(resource);
		return true;
	}

	@Override
	public boolean updateResource(Resource resource) {
		baseDao.update(resource);
		return true;
	}
}
